// Fill out your copyright notice in the Description page of Project Settings.

#pragma once

#include "CoreMinimal.h"
#include "GameFramework/Actor.h"
#include "MovableActorBase.generated.h"


UENUM(BlueprintType)
enum class ETransformMode:uint8
{
	ETM_Translation UMETA(DisplayName="Translation"),
	ETM_Rotation UMETA(DisplayName="Rotation"),
	ETM_Scale UMETA(DisplayName="Scale")
};

enum class ETransformAxes:uint8
{
	ECA_Org,
	ECA_X,
	ECA_Y,
	ECA_Z,
	ECA_XY,
	ECA_XZ,
	ECA_YZ,
	ECA_XYZ
};

enum class EHandlePriority:uint8
{
	EHP_First,
	EHP_Second,
	EHP_Third
};

struct FControlHandleInfo
{
	FName HandleName;
	ETransformMode HandleTranformMode;
	ETransformAxes HandleTranformAxes;
	EHandlePriority HandlePriority;
};

UCLASS()
class RUNTIMEMOVABLEACTOR_API AMovableActorBase : public AActor
{
	GENERATED_BODY()

	friend class UMovableInteractionComponent;
public:	
	AMovableActorBase();

protected:
	virtual void BeginPlay() override;

public:	
	virtual void Tick(float DeltaTime) override;

	/**
	 * 设置显示隐藏控制手柄
	 * @param Visi 
	 */
	UFUNCTION(BlueprintCallable, Category="Movable Interaction")
	void SetControlHandleVisible(bool Visi, ETransformMode HandleTranformMode);

	/**
	 * 设置控制手柄状态为悬浮
	 */
	void SetHandleStateHover(UStaticMeshComponent* Handle);

	/**
	 * 重置控制手柄状态
	 */
	void ResetHandleState(UStaticMeshComponent* Handle);

	/**
	 * 返回控制手柄变换类型
	 * @return 
	 */
	ETransformMode GetHandleTranformMode(UStaticMeshComponent* Handle) const;

	/**
	 * 获取控制手柄变换轴
	 * @param Handle 
	 * @return 
	 */
	ETransformAxes GetHandleTranformAxes(UStaticMeshComponent* Handle) const;

	/**
	 * 获取控制手柄检测优先级
	 * @param Handle 
	 * @return 
	 */
	EHandlePriority GetHandlePriority(UStaticMeshComponent* Handle) const;
	
	/**
	 * 是否是控制手柄
	 * @return 
	 */
	bool IsControlHandle(UStaticMeshComponent* Handle);

protected:
#pragma region Components
	UPROPERTY(EditDefaultsOnly, BlueprintReadOnly)
	UStaticMeshComponent* Mesh;

	UPROPERTY(EditDefaultsOnly, BlueprintReadOnly)
	USceneComponent* Grp_Transform;
// ----------------------- Translation --------------------------------
	UPROPERTY(EditDefaultsOnly, BlueprintReadOnly)
	USceneComponent* Grp_Translation;

	UPROPERTY(EditDefaultsOnly, BlueprintReadOnly)
	UStaticMeshComponent* Translation_Orig_Mesh;
	
	UPROPERTY(EditDefaultsOnly, BlueprintReadOnly)
	UStaticMeshComponent* Translation_X_Mesh;

	UPROPERTY(EditDefaultsOnly, BlueprintReadOnly)
	UStaticMeshComponent* Translation_Y_Mesh;

	UPROPERTY(EditDefaultsOnly, BlueprintReadOnly)
	UStaticMeshComponent* Translation_Z_Mesh;

	UPROPERTY(EditDefaultsOnly, BlueprintReadOnly)
	UStaticMeshComponent* Translation_XY_Mesh;

	UPROPERTY(EditDefaultsOnly, BlueprintReadOnly)
	UStaticMeshComponent* Translation_XZ_Mesh;

	UPROPERTY(EditDefaultsOnly, BlueprintReadOnly)
	UStaticMeshComponent* Translation_YZ_Mesh;
	
// ----------------------- Rotation --------------------------------
	UPROPERTY(EditDefaultsOnly, BlueprintReadOnly)
	USceneComponent* Grp_Rotation;

	UPROPERTY(EditDefaultsOnly, BlueprintReadOnly)
	UStaticMeshComponent* Rotation_X_Mesh;

	UPROPERTY(EditDefaultsOnly, BlueprintReadOnly)
	UStaticMeshComponent* Rotation_Y_Mesh;

	UPROPERTY(EditDefaultsOnly, BlueprintReadOnly)
	UStaticMeshComponent* Rotation_Z_Mesh;

	UPROPERTY(EditDefaultsOnly, BlueprintReadOnly)
	UStaticMeshComponent* Rotation_XYZ_Mesh;

	UPROPERTY(EditDefaultsOnly, BlueprintReadOnly)
	UStaticMeshComponent* Rotation_Screen_Mesh;

// ----------------------- Scale -----------------------------------
	UPROPERTY(EditDefaultsOnly, BlueprintReadOnly)
	USceneComponent* Grp_Scale;

	UPROPERTY(EditDefaultsOnly, BlueprintReadOnly)
	UStaticMeshComponent* Scale_Orig_Mesh;

	UPROPERTY(EditDefaultsOnly, BlueprintReadOnly)
	UStaticMeshComponent* Scale_X_Mesh;

	UPROPERTY(EditDefaultsOnly, BlueprintReadOnly)
	UStaticMeshComponent* Scale_Y_Mesh;

	UPROPERTY(EditDefaultsOnly, BlueprintReadOnly)
	UStaticMeshComponent* Scale_Z_Mesh;

	UPROPERTY(EditDefaultsOnly, BlueprintReadOnly)
	UStaticMeshComponent* Scale_XY_Mesh;

	UPROPERTY(EditDefaultsOnly, BlueprintReadOnly)
	UStaticMeshComponent* Scale_XZ_Mesh;

	UPROPERTY(EditDefaultsOnly, BlueprintReadOnly)
	UStaticMeshComponent* Scale_YZ_Mesh;
	
#pragma endregion

	FVector DefaultBound_Orig;
	FVector DefaultBound_Extend;

	TMap<UStaticMeshComponent*, FControlHandleInfo> ControlHandleMap;

	UPROPERTY(EditDefaultsOnly, Category="Movable Interaction", meta=(AllowPrivateAccess=true))
	UMaterialInstance* Handle_Org;
	
	UPROPERTY(EditDefaultsOnly, Category="Movable Interaction", meta=(AllowPrivateAccess=true))
	UMaterialInstance* Handle_X;

	UPROPERTY(EditDefaultsOnly, Category="Movable Interaction", meta=(AllowPrivateAccess=true))
	UMaterialInstance* Handle_Y;

	UPROPERTY(EditDefaultsOnly, Category="Movable Interaction", meta=(AllowPrivateAccess=true))
	UMaterialInstance* Handle_Z;

	UPROPERTY(EditDefaultsOnly, Category="Movable Interaction", meta=(AllowPrivateAccess=true))
	UMaterialInstance* Handle_Hover;

	UPROPERTY(EditDefaultsOnly, Category="Movable Interaction", meta=(AllowPrivateAccess=true))
	UMaterialInstance* Handle_RotationBall;

	UPROPERTY(EditAnywhere, BlueprintReadWrite, Category="Movable Interaction", meta=(AllowPrivateAccess=true))
	bool bDebugAxes = false;
};

